package com.chuangsi.project.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chuangsi.common.config.UploadDataListener;
import com.chuangsi.common.enums.OrderStatusEnum;
import com.chuangsi.common.exception.ServiceException;
import com.chuangsi.common.utils.*;
import com.chuangsi.common.utils.file.FileUploadUtils;
import com.chuangsi.framework.aspectj.lang.annotation.DataScope;
import com.chuangsi.framework.config.ChuangSiConfig;
import com.chuangsi.project.admin.domain.*;
import com.chuangsi.project.admin.dto.admin.approve.ReqApplyBackDto;
import com.chuangsi.project.admin.dto.admin.index.ResIndexDto;
import com.chuangsi.project.admin.dto.admin.order.*;
import com.chuangsi.project.admin.dto.app.ReqAppletsOrderPageDto;
import com.chuangsi.project.admin.dto.app.ResAppletsOrderPageDto;
import com.chuangsi.project.admin.dto.app.esign.*;
import com.chuangsi.project.admin.dto.app.order.*;
import com.chuangsi.project.admin.dto.common.SelectDto;
import com.chuangsi.project.admin.dto.esign.*;
import com.chuangsi.project.admin.mapper.OrderMapper;
import com.chuangsi.project.admin.service.*;
import com.chuangsi.project.system.domain.File;
import com.chuangsi.project.admin.domain.Product;
import com.chuangsi.project.system.domain.SysDept;
import com.chuangsi.project.system.service.ISysDeptService;
import com.chuangsi.project.system.service.ISysUserService;
import com.chuangsi.project.wechat.PayUtil;
import com.itextpdf.text.pdf.PdfReader;
import com.wechat.pay.java.core.Config;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author ywb
 * @since 2023-03-23
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    //这里是Order里面存放很多内容的字段，在做一些查询的时候不需要用到这个字段，就先排出他
    List<String> BIG_COLUMN_LIST = Arrays.asList("agreement_detail","self_field");
    @Resource
    private PayUtil payUtil;
    @Autowired
    private ApproveService approveService;
    @Autowired
    private FileService fileService;
    @Autowired
    private ApproveConfigService approveConfigService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ConfigUtil configUtil;
    @Autowired
    private AgreementService agreementService;
    @Autowired
    private SealService sealService;
    @Autowired
    private ITLogService logService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private ISysDeptService deptService;
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public void export(ReqOrderPageDto dto, HttpServletResponse response) {
        List<ResOrderExportDto> data = baseMapper.export(dto);
        Map<String, String> agreementMap = baseMapper.getOtherContent("agreement_detail", dto).stream().collect(Collectors.toMap(ResOrderExportOtherDto::getOrderId, ResOrderExportOtherDto::getContent));
        for (int i = 0; i < data.size(); i++) {
            ResOrderExportDto exportDto = data.get(i);
            exportDto.setIndex(i + 1);
            cn.hutool.json.JSONArray array = JSONUtil.parseArray(exportDto.getSelfField());
            for (Object object : array) {
                JSONObject json = JSONUtil.parseObj(object);
                String insertData = json.getStr("InsertData");
                String value = json.getStr("value", "");
                if (insertData.equals("新车发票日期")) {
                    exportDto.setBuyTime(value);
                }
                if (insertData.equals("品牌")) {
                    exportDto.setModel(value + exportDto.getModel());
                }
                if (insertData.equals("车型")) {
                    exportDto.setModel(value);
                }
                if (insertData.equals("首付金额") && exportDto.getPayType().equals("2")) {
                    int soufu;
                    try {
                        soufu = Integer.parseInt(value);
                    } catch (Exception e) {
                        soufu = 0;
                    }
                    exportDto.setShoufuMoney(BigDecimal.valueOf(soufu).toString());
                    exportDto.setFenqiMoney(String.valueOf(BigDecimal.valueOf(Double.parseDouble(exportDto.getMoney())).subtract(BigDecimal.valueOf(Double.parseDouble(exportDto.getShoufuMoney())))));
                }
                if(insertData.contains("产品名称")){
                    exportDto.setProductName(value);
                }
                if(insertData.contains("补偿方案")){
                    exportDto.setCompensationPlan(value);
                }
            }
            exportDto.setType(exportDto.getType().equals("1") ? "代销A" : exportDto.getType().equals("2") ? "代销B" : "传统");
            if (exportDto.getPayType().equals("1")) {
                exportDto.setShoufuMoney("-");
                exportDto.setFenqiMoney("-");
            }
            exportDto.setQuankuanMoney(exportDto.getMoney());
            exportDto.setPayType(exportDto.getPayType().equals("1") ? "全款" : "分期");
            String html = agreementMap.getOrDefault(exportDto.getOrderId(),"");
            // 提取单个字段
            String productName = SimpleHtmlExtractor.extract(html, "产品名称");
            // 提取单个字段
            String extended = SimpleHtmlExtractor.extract(html, "延保期限");
            exportDto.setExtended(extended);
            exportDto.setProductName(productName);
            exportDto.setSelfField("");
            exportDto.setAppStatus(OrderStatusEnum.getName(exportDto.getAppStatus()));
            if (StrUtil.isNotBlank(exportDto.getOurselfBuy())) {
                exportDto.setOurselfBuy(exportDto.getOurselfBuy().equals("1") ? "是" : "否");
            } else {
                exportDto.setOurselfBuy("-");
            }
        }
        ExcelUtil.export(data, ResOrderExportDto.class, "订单记录" + LocalDate.now(), response);
    }

    @Override
    public void remark(ReqRemarkDto req) {
        update(Wrappers.lambdaUpdate(Order.class)
                .eq(Order::getOrderId, req.getOrderId())
                .set(Order::getRemark, req.getRemark())
                .set(Order::getUpdateTime, LocalDateTime.now())
        );
    }

    @Override
    public List<SelectDto> orderStatusSelect() {
        return Arrays.stream(OrderStatusEnum.values()).map(x -> new SelectDto(x.getStatus().toString(), x.getStatusName())).collect(Collectors.toList());
    }

    @Override
    public void changeStatus(ReqOrderChangeStatusDto dto) {
        Order order = getSimpleOrder(dto.getOrderId());
        Assert.notNull(order, "未找到订单");
        if (!OrderStatusEnum.exist(dto.getAppStatus())) {
            throw new ServiceException("错误状态");
        }
        update(Wrappers.lambdaUpdate(Order.class)
                .eq(Order::getOrderId, order.getOrderId())
                .set(Order::getAppStatus, dto.getAppStatus())
                .set(Order::getUpdateTime, LocalDateTime.now()));
        String userName = SecurityUtils.getNickName();
        String template = "时间：%s,操作人：%s,改变了订单号：%s，改变前状态：%s，改变后状态：%s";
        String logMsg = String.format(template, LocalDateTimeUtils.formatNow(LocalDateTimeUtils.YYYYMMDDHHMMSS), userName, order.getOrderNo(), OrderStatusEnum.getName(order.getAppStatus()), OrderStatusEnum.getName(dto.getAppStatus()));
        //获取request对象
        TLog tlog = new TLog();
        tlog.setUserName(userName);
        tlog.setModule("订单管理");
        tlog.setMethods("OrderServiceImpl.changeStatus");
        tlog.setContent(logMsg);
        tlog.setActionurl("/adminApi/order/changeStatus");
        tlog.setIp(Tool.getIp());
        tlog.setCommite("1");
        tlog.setMsg("");
        tlog.setCreateTime(LocalDateTime.now());
        logService.insert(tlog);
        log.warn(logMsg);
    }


    @Override
    public Order getSimpleOrder(String orderId) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery(Order.class);
        wrapper.select(Order.class, o -> !BIG_COLUMN_LIST.contains(o.getColumn()));
        wrapper.eq(Order::getOrderId,orderId);
        return getOne(wrapper);
    }

    @Override
    public ResOrderAppletsDetailDto orderDetailForUser() {
        Order order = getOne(Wrappers.lambdaQuery(Order.class).select(Order.class, o -> !BIG_COLUMN_LIST.contains(o.getColumn())).eq(Order::getCustomerUserId,SecurityUtils.getUserId()).orderByDesc(Order::getCreateTime).last(" limit 1"));
        ResOrderAppletsDetailDto res = new ResOrderAppletsDetailDto();
        Assert.notNull(order,"未查询到订单详情");
        BeanUtils.copyProperties(order, res);
        res.setNickName(userService.selectNickNameById(order.getUserId()));
        res.setFileList(fileService.getFileList(order.getOrderId()));
        res.setOurselfBuy(order.getOurselfBuy() != null?order.getOurselfBuy().equals(1) ? "是" : "否":"-");
        res.setAppStatus(OrderStatusEnum.getName(order.getAppStatus()));
        res.setInvoiceUris(order.getInvoiceUris());
        return res;
    }

    @Override
    public void applyInvoice(ReqApplyInvoiceDto req) {
        Order  order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未找到订单");
        Assert.isTrue(!order.getUserId().equals(SecurityUtils.getUserId()),"该订单不是您的，不能发起申请开票");
        if(!order.getAppStatus().equals("2")){
            throw new ServiceException("订单状态为："+OrderStatusEnum.getName(order.getAppStatus())+",不能申请");
        }
        if(order.getInvoiceStatus().equals(3)){
            throw new ServiceException("发票已开具，不能重新申请");
        }
        LambdaUpdateWrapper<Order> wrapper = Wrappers.lambdaUpdate(Order.class);
        wrapper.eq(Order::getOrderId,req.getOrderId());
        wrapper.set(Order::getInvoiceStatus,2);
        wrapper.set(Order::getInvoiceHeader,req.getInvoiceHeader());
        wrapper.set(Order::getSocialCreditCode,req.getSocialCreditCode());
        wrapper.set(Order::getOpeningBank,req.getOpeningBank());
        wrapper.set(Order::getAccountNumber,req.getAccountNumber());
        wrapper.set(Order::getPhone,req.getPhone());
        wrapper.set(Order::getAddress,req.getAddress());
        wrapper.set(Order::getInvoiceRemark,req.getInvoiceRemark());
        update(wrapper);
    }

    @Override
    public void uploadAttachments(ReqUploadAttachmentsDto req) {
        Order order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未找到合同订单");
        Assert.isTrue(req.getFileList() == null || req.getFileList().isEmpty(),"请上传附件");
        //存图片
        if (CollectionUtils.isNotEmpty(req.getFileList())) {
            List<File> list = new ArrayList<>();
            for (FileDto i : req.getFileList()) {
                File file = new File();
                file.setUri(i.getUri());
                file.setFileName(i.getFileName());
                file.setSourceId(req.getOrderId());
                file.setFileType(i.getFileType());
                list.add(file);
            }
            fileService.saveBatch(list);
        }
    }

    @Override
    public boolean deleteFile(String id) {
        File file = fileService.getById(id);
        Assert.notNull(file,"未查到文件");
        String path = configUtil.getUrl()+file.getUri();
        java.io.File file1 = new java.io.File(path);
        if (file1.exists()) {
            file1.delete();
        }
        return fileService.removeById(id);
    }

    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<ResOrderPageDto> pageQuery(ReqOrderPageDto req) {
        return baseMapper.pageQuery(req);
    }

    @Override
    public ResOrderDetailDto detail(ReqOrderDetailDto req) {
        ResOrderDetailDto res = new ResOrderDetailDto();
        Order order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未查询到订单详情");
        BeanUtil.copyProperties(order, res);
        res.setNickName(userService.selectNickNameById(order.getUserId()));
        //获取附件
        res.setFileList(fileService.getFileList(req.getOrderId()));
        List<ResAppStatusListDto> list = approveService.list(new LambdaQueryWrapper<Approve>()
                .eq(Approve::getSourceId, order.getOrderId()).orderByAsc(Approve::getSort)).stream().map(m -> {
            ResAppStatusListDto r = new ResAppStatusListDto();
            BeanUtils.copyProperties(m, r);
            String nickName = userService.selectNickNameById(m.getUserId());
            if (StrUtil.isNotBlank(nickName)) {
                r.setNickName(nickName);
            }
            return r;
        }).collect(Collectors.toList());
        Long userId = SecurityUtils.getUserId();
        //判断是否该当前用户审批
        List<ResAppStatusListDto> now = list.stream().filter(m -> m.getIsPass() == null).sorted(Comparator.comparing(ResAppStatusListDto::getSort)).collect(Collectors.toList());
        if (!now.isEmpty()) {
            res.setIsMy(now.get(0).getUserId().equals(userId) ? "1" : "2");
        }
        if (order.getOurselfBuy() != null) {
            res.setOurselfBuy(order.getOurselfBuy() == 1 ? "是" : "否");
        }
        res.setAppStatus(OrderStatusEnum.getName(order.getAppStatus()));
        res.setAppList(list);
        return res;
    }

    @Override
    public boolean pass(ReqOrderPassDto req) {
        Order order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未查询到订单详情");
        LambdaUpdateWrapper<Approve> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Approve::getSourceId, req.getOrderId());
        wrapper.eq(Approve::getUserId, SecurityUtils.getUserId());
        if ("2".equals(req.getAppStatus()) || "5".equals(req.getAppStatus())) {
            wrapper.set(Approve::getIsPass, "1");
            wrapper.set(Approve::getPassTime, LocalDateTime.now());
            if ("2".equals(req.getAppStatus())) {
                Product product = productService.getById(order.getProductId());
                if (product != null) {
                    product.setVolume(product.getVolume() + 1);
                    productService.updateById(product);
                }
            }
        } else if ("3".equals(req.getAppStatus()) || "6".equals(req.getAppStatus())) {
            wrapper.set(Approve::getIsPass, "2");
            wrapper.set(Approve::getPassTime, LocalDateTime.now());
        }
        approveService.update(wrapper);
        //查询是否还有未通过的，如果没有未通过的，那么就算通过
        int count = approveService.count(new LambdaQueryWrapper<Approve>().eq(Approve::getSourceId, req.getOrderId()).eq(Approve::getIsPass, "2"));
        if (count == 0) {
            update(Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderId,req.getOrderId()).set(Order::getAppStatus,req.getAppStatus()));
        }
        return true;
    }

    @Override
    public OrderIdDto sign(ReqSignDto req) {
        PayOrder payOrder = payOrderService.getById(req.getPayOrderId());
        Assert.notNull(payOrder, "未找到支付订单");
        Assert.isTrue(!payOrder.getUserId().equals(SecurityUtils.getUserId()), "该订单不是你发起的，不能进行合同签署");
        Assert.isTrue(!payOrder.getStatus().equals(2), "该订单状态异常，不能进行合同签署");
        //设置印章
        Product product = productService.getById(req.getProductId());
        Assert.notNull(product, "未找到产品");
        Seal seal = sealService.getById(product.getSealId());
        Assert.notNull(seal, "未找到印章");
        if(product.getEsignContract().equals("Y")){
            if(StrUtil.isBlank(seal.getAppId()) ||
                    StrUtil.isBlank(seal.getAppSecret()) ||
                    StrUtil.isBlank(seal.getOrgId()) ||
                    StrUtil.isBlank(seal.getPsnId()) ||
                    StrUtil.isBlank(seal.getEsignSealId()) ){
                throw new ServiceException("印章:"+seal.getSealName()+"没有配置完整的E签宝属性，请联系系统管理员配置");
            }
        }
        Order order = new Order();
        BeanUtils.copyProperties(req, order);
        long timeInMillis = Calendar.getInstance().getTimeInMillis();
        order.setDeptId(req.getDeptId());
        order.setOrderNo(String.valueOf(timeInMillis));
        order.setUserId(SecurityUtils.getUserId());
        order.setCarInvoicePrice(req.getCarInvoicePrice());
        //order.setCustomerUserId(payOrder.getCustomerUserId());
        order.setSealId(seal.getSealId());
        order.setPayOrderId(payOrder.getPayOrderId());//关联支付订单
        order.setEsignContract(product.getEsignContract());
        this.save(order);
        //根据配置生成审批流程
        List<ApproveConfig> appList = approveConfigService.list(new LambdaQueryWrapper<ApproveConfig>().eq(ApproveConfig::getType, "2"));
        if (CollectionUtils.isNotEmpty(appList)) {
            List<Approve> list = new ArrayList<>();
            for (ApproveConfig i : appList) {
                Approve approve = new Approve();
                approve.setUserId(i.getUserId());
                approve.setSort(i.getSort());
                approve.setSourceId(order.getOrderId());
                approve.setType("1");
                list.add(approve);
            }
            approveService.saveBatch(list);
        }
        //存图片
        if (CollectionUtils.isNotEmpty(req.getFileList())) {
            List<File> list = new ArrayList<>();
            for (FileDto i : req.getFileList()) {
                File file = new File();
                file.setUri(i.getUri());
                file.setFileName(i.getFileName());
                file.setSourceId(order.getOrderId());
                file.setFileType(i.getFileType());
                list.add(file);
            }
            fileService.saveBatch(list);
        }
        OrderIdDto resSignDto = new OrderIdDto();
        resSignDto.setOrderId(order.getOrderId());
        return resSignDto;
    }

    @Override
    public ResIndexDto indexInfo() {
        ResIndexDto res = new ResIndexDto();
//        LocalDate now = LocalDate.now();
//        List<Admin> admins = adminService.list();
//        //销售人员数量
//        res.setSalesmanCount(admins.size());
//        List<Department> departments = departmentService.list();
//        //经销商数量
//        res.setDepartmentCount(departments.size());
//        List<Order> orderList = this.list(new LambdaQueryWrapper<Order>().ge(Order::getAppStatus,"2")
//        .in(Order::getDepartmentId,departments.stream().map(Department::getDepartmentId).collect(Collectors.toList())));
//        //经销商出单数量
//        res.setDepartmentOrder(orderList.size());
//        //经销商销售金额
//        BigDecimal reduce = orderList.stream().map(Order::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//        res.setDepartmentMoney(reduce);
//        //今日出单数量
//        List<Order> orderListToday = this.list(new LambdaQueryWrapper<Order>().ge(Order::getAppStatus,"2")
//        .ge(Order::getCreateTime, LocalDateTime.of(now, LocalTime.MIN)).le(Order::getCreateTime,LocalDateTime.of(now, LocalTime.MAX)));
//        res.setTodayOrder(orderListToday.size());
//        //今日销售金额
//        BigDecimal reduceToday = orderListToday.stream().map(Order::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//        res.setTodayMoney(reduceToday);
//        //本月出单数量
//        List<Order> orderListMonth = this.list(new LambdaQueryWrapper<Order>().ge(Order::getAppStatus,"2")
//                .ge(Order::getCreateTime, LocalDateTime.of(now.with(TemporalAdjusters.firstDayOfMonth()),LocalTime.MIN))
//                .le(Order::getCreateTime,LocalDateTime.of(now.with(TemporalAdjusters.lastDayOfMonth()),LocalTime.MAX)));
//        res.setMonthOrder(orderListMonth.size());
//        //本月销售金额
//        BigDecimal reduceMonth = orderListMonth.stream().map(Order::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//        res.setMonthMoney(reduceMonth);
        return res;
    }

    @Override
    public List<ResAppletsOrderPageDto> orderPageQuery(ReqAppletsOrderPageDto req) {
        List<ResAppletsOrderPageDto> data = baseMapper.orderPageQuery(req,SecurityUtils.getUserId());
        for (ResAppletsOrderPageDto datum : data) {
            if (datum.getOurselfBuy() != null) {
                datum.setOurselfBuy(datum.getOurselfBuy().equals("1") ? "是" : "否");
            } else {
                datum.setOurselfBuy("-");
            }
        }
        return data;
    }

    @Override
    public ResOrderAppletsDetailDto orderDetail(ReqOrderDetailDto req) {
        ResOrderAppletsDetailDto res = new ResOrderAppletsDetailDto();
        Order order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未查询到订单详情");
        BeanUtils.copyProperties(order, res);
        res.setNickName(userService.selectNickNameById(order.getUserId()));
        res.setFileList(fileService.getFileList(req.getOrderId()));
        res.setOurselfBuy(order.getOurselfBuy() != null?order.getOurselfBuy().equals(1) ? "是" : "否":"-");
        res.setAppStatus(OrderStatusEnum.getName(order.getAppStatus()));
        res.setInvoiceUris(order.getInvoiceUris());
        PayOrder payOrder = payOrderService.getById(order.getPayOrderId());
        if(payOrder != null){
            res.setOrderType(payOrder.getOrderType());
            //线上
            if(payOrder.getOrderType().equals(1)){
                res.setOutTradeNo(payOrder.getOutTradeNo());
            }
            //线下
            if(payOrder.getOrderType().equals(2)){
                res.setOfflinePayPics(payOrder.getOfflinePayPics());
            }
        }
        return res;
    }

    @Override
    public boolean applyBack(ReqApplyBackDto req) {
        Order order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未查询到订单详情");
        //修改订单状态
        update(Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderId,req.getOrderId()).set(Order::getAppStatus,req.getAppStatus()));
        int count = approveService.count(new LambdaQueryWrapper<Approve>().eq(Approve::getSourceId, order.getOrderId()));
        //根据配置生成审批流程
        List<ApproveConfig> appList = approveConfigService.list(new LambdaQueryWrapper<ApproveConfig>().eq(ApproveConfig::getType, "3"));
        if (CollectionUtils.isNotEmpty(appList)) {
            List<Approve> list = new ArrayList<>();
            for (ApproveConfig i : appList) {
                Approve approve = new Approve();
                approve.setUserId(i.getUserId());
                approve.setSort(i.getSort() + count);
                approve.setSourceId(order.getOrderId());
                approve.setType("1");
                list.add(approve);
            }
            approveService.saveBatch(list);
        }
        return true;
    }

//    @PostConstruct
    void aaass() throws Exception {
        String html = "<p style=\"margin-top: 3px; margin-bottom: 3px;\"><span style=\"letter-spacing: 0px; font-size: 10px;\">1点滴小投入</span><span style=\"font-family: Calibri; letter-spacing: 0px; font-size: 10px;\">&nbsp;</span><span style=\"letter-spacing: 0px; font-size: 10px;\">● 爱车大保障 &nbsp;</span></p><p style=\"margin-top: 3px; margin-bottom: 3px;\"><strong><span style=\"color: #CF1322; letter-spacing: 0px; font-size: 10px; font-family: 宋体;\">合同号</span></strong><span style=\"letter-spacing: 0px; font-size: 10px;\">：</span><span style=\"font-family: Calibri; letter-spacing: 0px; font-size: 10px;\">&nbsp;1742807544400</span></p><p style=\"margin-top: 3px; margin-bottom: 3px;\"><span style=\"letter-spacing: 0px; font-size: 10px;\">客服电话：</span><span style=\"font-family: Calibri; letter-spacing: 0px; font-size: 10px;\">400-900-7937</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">&nbsp;</span></p><p style=\"text-indent: 43px; text-align: center; line-height: 24px;\"><strong><span style=\"font-family: 宋体; line-height: 31.5px; font-size: 21px;\">汽车延长质量保修服务合同</span></strong></p><p style=\"text-indent: 37px; text-align: center; line-height: 24px;\"><strong><span style=\"font-family: 宋体; line-height: 28.5px; font-size: 19px;\">基本信息</span></strong></p><p style=\"margin-top: 3px; margin-bottom: 3px;\"><strong><span style=\"letter-spacing: 0px; font-size: 12px; font-family: 宋体;\">客户信息</span></strong></p><p style=\"margin-top: 4px; margin-bottom: 4px; line-height: 24px;\"><span style=\"font-family: 宋体; line-height: 19.5px; letter-spacing: 0px; font-size: 13px;\">个人客户姓名/企业客户名称：冯跃龙</span></p><p style=\"margin-top: 4px; margin-bottom: 4px; line-height: 24px;\"><span style=\"font-family: 宋体; line-height: 19.5px; letter-spacing: 0px; font-size: 13px;\">证件类型：身份证</span></p><p style=\"margin-top: 4px; margin-bottom: 4px; line-height: 24px;\"><span style=\"font-family: 宋体; line-height: 19.5px; letter-spacing: 0px; font-size: 13px;\">联系电话：18398522178</span></p><p style=\"margin-top: 3px; margin-bottom: 3px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\">&nbsp;</span></strong></p><p style=\"line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\">附件</span></strong></p><p style=\"text-indent: 37px; text-align: center; line-height: 24px;\"><strong><span style=\"font-family: 宋体; line-height: 28.5px; font-size: 19px;\">汽车延长质量保修服务合同</span></strong></p><p style=\"text-indent: 37px; text-align: center; line-height: 24px;\"><strong><span style=\"font-family: 宋体; line-height: 28.5px; font-size: 19px;\">延保范围</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">重庆创虹汽车服务有限公司提供延保服务范围为：延保车辆出厂原装零部件范围（经过改装、加装使用的设备和零部件不属于延保范围），具体如下：</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\">一、被保修部件：</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">1</span>、发动机</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">缸体、气缸体轴瓦、曲轴、轴承盖轴瓦、轴承盖、止推垫片、飞轮、机油泵、集滤器、机油喷嘴、连杆轴承盖、连杆轴&nbsp;瓦、活塞卡环、活塞销、活塞、活塞环、连杆、机油尺导向管、凸轮轴调节电磁阀、正时链上盖板、正时链下盖板、正&nbsp;时链条张紧器、正时链条张紧轨、凸轮轴正时链条滑轨、凸轮轴正时链、平衡轴、平衡轴管、中间轴齿轮、正时链、滑&nbsp;轨、气门、气缸盖、气门导管、气门弹簧、气门锁夹、凸轮轴、气门挺杆、弹簧座、摇臂、摇臂轴、气门室罩盖、缸盖&nbsp;垫、机油冷却器、曲轴箱通风阀、真空泵、曲轴油封、发动机大修修理包（仅在发动机大修时保修）、气门室盖垫、正&nbsp;时盖垫、油底壳垫</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">2</span>、变速箱：</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">轴、轴承、太阳轮、行星齿轮、制动带、传动盘、传动齿轮、油泵、换挡拉线、变速器支架、油尺和油尺导管、内部液&nbsp;压管路、输入轴油封、油温传感器、变速箱壳体（仅在由其内部延保范围内部件导致损坏时保修）</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">3</span>、传动系统：</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">传动轴、传动轴支撑、差速器轴承、传动轴万向节、主减速器、差速器（内部润滑部件）、差速器锁、驱动轴、等速万&nbsp;向节、差速器齿轮、差速器油封、驱动桥壳（仅在由其内部延保范围内部件导致损坏时保修）</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">4</span>、冷却系统：</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">冷却风扇电机、散热器、节温器、冷却液水壶盖、冷却液水壶、冷却液水泵</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">5</span>、燃油供给系统：</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">燃油泵、金属油管、压力调节器、油轨、高压燃油油泵、通风管、活性碳罐电磁阀、油门踏板模块、踏板座、燃油位置&nbsp;传感器、油箱</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">6</span>、电子燃油喷射系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">空气流量计、曲轴位置传感器、发动机转速传感器、进气压力传感器、水温传感器、进气温度传感器、凸轮轴位置传感&nbsp;器、机油压力传感器、爆震传感器、机油油位传感器、<span style=\"font-family: Calibri;\">EGR&nbsp;</span>阀、发动机控制单元。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">7</span>、行驶系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">轮毂轴承、平衡杆、平衡杆连接杆、水平高度传感器、水平高度控制单元。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">8</span>、电气系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">发电机、档位开关、巡航定速开关、巡航控制传感器、巡航控制电机、组合仪表、座椅开关、座椅记忆开关、座椅电&nbsp;机、后视镜开关、后视镜折叠开关、后视镜电机、点火开关、点火线圈、点火模块、起动机、起动机继电器、雨刮开&nbsp;关、雨刮电机、雨刮清洗电机、雨量传感器、中控锁开关、油箱盖马达、中央防盗控制单元、后备箱开关、油箱盖开&nbsp;关、导航控制单元、收音机、<span style=\"font-family: Calibri;\">CD&nbsp;</span>机、扬声器、视频<span style=\"font-family: Calibri;\">/</span>多媒体播放器、收音机天线、天窗开关、天窗电机。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">9</span>、转向系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">电子转向机、转向柱、转向连接杆（转向柱到方向机）、方向盘。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">10</span>、进气、排气系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">进气歧管、排气歧管、中段消音器、后段消音器、二次空气压力传感器、二次空气喷射阀、二次空气泵马达。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">11</span>、空调系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">空调压缩机、压缩机离合器、空调高低压力传感器、蒸发箱温度传感器、蒸发箱、暖风水箱、空调伺服电机、空调开关、空调控制单元、空调&nbsp;<span style=\"font-family: Calibri;\">O&nbsp;</span>形密封圈。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">12</span>、<span style=\"font-family: Calibri;\">ABS&nbsp;</span>防抱死制动系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">ABS&nbsp;</span>传感器、电子驻车控制单元、制动信号灯开关、<span style=\"font-family: Calibri;\">ABS&nbsp;</span>液压控制单元、转向角度传感器、<span style=\"font-family: Calibri;\">AUTO HOLD&nbsp;</span>按键、驻车制动器 开关、电控机械式驻车制动器伺服马达、制动总泵、制动分泵、真空助力器、制动力分配阀、液压管路、制动踏板、制 动踏板支架、制动钳、<span style=\"font-family: Calibri;\">O&nbsp;</span>形密封圈。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">13</span>、安全气囊系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">安全气囊模块<span style=\"font-family: Calibri;\">(</span>未开过封条<span style=\"font-family: Calibri;\">/</span>事故无效）、安全气囊碰撞传感器、安全气囊、安全带收紧器、安全带收紧器马达、安全带。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">14</span>、灯光照明系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">示宽灯开关、大灯开关、大灯变光开关、雾灯开关、转向灯开关、双闪灯开关、大灯清洗开关、仪表照明调节开关。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">15</span>、涡轮增压系统</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">涡轮增压器、中冷器、增压空气冷却器、增压压力传感器、涡轮增压器的测压计、增压压力限制电磁阀。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">16</span>、车身</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">车身骨架、纵梁、横梁、车门。</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><strong><span style=\"font-family: 宋体; font-size: 14px;\">二、不被保修的部件：</span></strong></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-size: 14px; font-family: 宋体;\">凡没有在“被保修部件”中列明的零部件，或虽然被列明但并非是由车辆制造商或其授权特约维修商提供并安装在车辆上的零部件，均不属于保修方案的被保修零部件，包括但不限于：</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">1.&nbsp;</span>车辆出厂标准配置以外的任何改装、加装或零部件的变更；</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\"><span style=\"font-family: Calibri;\">2.&nbsp;</span>人为、外力、噪音、油和液等流体轻微渗漏<span style=\"font-family: Calibri;\">(</span>不影响车辆正常使用的情况下<span style=\"font-family: Calibri;\">)</span>、机油损耗（机油损耗量根据各品牌生产厂家规定的标准执行）等情况</span></p><p style=\"margin-top: 4px; margin-bottom: 4px;\"><span style=\"font-size: 12px;\"><strong><span style=\"font-family: 宋体;\">客户确认：</span></strong></span></p><p style=\"margin-top: 4px; margin-bottom: 4px;\"><span style=\"font-size: 12px;\"><span style=\"font-family: Calibri;\"><span style=\"font-family: 宋体;\">我已阅读并确认本合同条款内容，特别是</span>“<span style=\"font-family: 宋体;\">合同生效日</span>”<span style=\"font-family: 宋体;\">、</span>“<span style=\"font-family: 宋体;\">免赔期</span>”<span style=\"font-family: 宋体;\">、理赔限额</span>”<span style=\"font-family: 宋体;\">和</span>“<span style=\"font-family: 宋体;\">责任免除</span>”<span style=\"font-family: 宋体;\">部分，不存在任何歧义或模糊&nbsp;</span>&nbsp;,<span style=\"font-family: 宋体;\">我已充分注意并理解其含义和法律后果，对</span></span><span style=\"font-family: 宋体;\">创虹</span><span style=\"font-family: Calibri;\"><span style=\"font-family: 宋体;\">销售的解释已充分理解。我已知悉：本合同包括基本信息、延保范围、合同条款三大部分；我签字后即视为已知悉本合同全部内容；本合同均以制式</span>(<span style=\"font-family: 宋体;\">打印</span>)<span style=\"font-family: 宋体;\">合同内容为准，任何以手写、口头等方式所作出的约 定或承诺均无法律效力；延保车辆原厂质保期以经销商承诺期限为准。</span></span></span></p><p style=\"margin-top: 4px; margin-bottom: 4px;\"><span style=\"font-family: Calibri; font-size: 12px;\">&nbsp;</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 12px;\">&nbsp;</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">&nbsp;</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">甲方签名：&nbsp;<span style=\"font-family: Calibri;\">&nbsp;</span>重庆创虹汽车服务有限公司</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">日&nbsp;<span style=\"font-family: Calibri;\">&nbsp; &nbsp;</span>期：<span style=\"font-family: Calibri;\">${dateA}</span></span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">&nbsp;</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">乙方签名：</span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: 宋体; font-size: 14px;\">日&nbsp;<span style=\"font-family: Calibri;\">&nbsp; &nbsp;</span>期：<span style=\"font-family: Calibri;\">${dateA}</span></span></p><p style=\"text-indent: 28px; line-height: 24px;\"><span style=\"font-family: Calibri; font-size: 14px;\">&nbsp;</span></p><p><br style=\"white-space: normal;\"/></p><p><br/></p>";
        //1.将接收的富文本转成pdf并上传至E签宝，先获取一个上传的地址，和文件id
        //java.io.File file = agreement.getAgreementName().contains("测试")?pdfUtil.getImgServerUrlApose(html):pdfUtil.getImgServerUrl(html);

        java.io.File dir = new java.io.File(ChuangSiConfig.getProfile()+"/contract");
        if (!dir.exists()) {
            dir.mkdir();
        }
        String path = dir + "/杨文博15696391732" + "-" + System.currentTimeMillis() + ".pdf";
        java.io.File file = PdfUtil.getImgServerUrlApose(html,path);
        String filePath = FileUploadUtils.upload(ChuangSiConfig.getUploadPath(), file);
        System.err.println(filePath);
    }

    @SneakyThrows
    @Override
    public ResESignGetFileUpDto signTurned(ReqESignGetFileUpDto req) {
        ResESignGetFileUpDto res = new ResESignGetFileUpDto();
        Order order = getSimpleOrder(req.getOrderId());
        if (order == null) {
            throw new ServiceException("获取订单详情失败");
        }
        Agreement agreement = agreementService.getById(order.getAgreementId());
        if (agreement == null) {
            throw new ServiceException("获取合同模板失败");
        }
        Seal seal = sealService.getById(order.getSealId());
        if (seal == null) {
            throw new ServiceException("获取印章失败");
        }
        //替换公司名称
        String html = req.getValue().replace("${coName}", seal.getSealName());
        //1.将接收的富文本转成pdf并上传至E签宝，先获取一个上传的地址，和文件id
        //java.io.File file = agreement.getAgreementName().contains("测试")?pdfUtil.getImgServerUrlApose(html):pdfUtil.getImgServerUrl(html);


        java.io.File dir = new java.io.File(ChuangSiConfig.getProfile()+"/contract");
        if (!dir.exists()) {
            dir.mkdir();
        }
        java.io.File file = PdfUtil.getImgServerUrlApose(html,dir+"/"+order.getCustomName()+order.getCustomPhone()+".pdf");
        res.setEsignContract(order.getEsignContract());
        //如果不使用E签宝，那么就直接保存合同
        if(order.getEsignContract().equals("N")){
            log.info("不需要E签宝，画章开始");
            //获取章的URL
            String sealUrl = configUtil.getUrl()+seal.getSealPic();
            PdfUtil.addSeal(file,sealUrl);
            log.info("不需要E签宝，画章结束，开始保存文件,地址：{}",file.getPath());
            String filePath = FileUploadUtils.upload(ChuangSiConfig.getUploadPath(), file);
            log.info("保存文件结束，地址：{}",filePath);
            order.setFilePath(filePath);
            order.updateById();
            res.setFilePath(filePath);
            return res;
        }
        //获取页数
        PdfReader pdfReader = new PdfReader(PdfUtil.getMultipartFile(file).getInputStream());
        //pdf页数
        int pdfPage = pdfReader.getNumberOfPages();
        String fileContentMD5 = ContentMD5Util.getFileContentMD5(file.getPath());
        ReqESignUploadFileDto fileStep1Dto = new ReqESignUploadFileDto();
        fileStep1Dto.setContentMd5(fileContentMD5);
        fileStep1Dto.setContentType("application/octet-stream");
        fileStep1Dto.setFileName(getFileName(order));
        fileStep1Dto.setFileSize(file.length());
        ResESignUploadFileDto uploadUrl = SignatureUtils.getUploadUrl(fileStep1Dto, seal);
        if (uploadUrl == null) {
            this.removeById(req.getOrderId());
            throw new ServiceException("获取上传文件地址失败");
        }
        if (0 != uploadUrl.getCode()) {
            this.removeById(req.getOrderId());
            throw new ServiceException("获取上传文件地址失败，错误为：" + uploadUrl.getMessage());
        }
        String fileId = uploadUrl.getData().getFileId();
        //添加文件id到订单
        update(Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderId,req.getOrderId()).set(Order::getFileId,fileId));
        log.info("获取文件地址和id返回结果:{}", uploadUrl.getData());
        //2.向上一步获得的地址上传文件，文件需转成字节流形式
        ReqESignUploadFileStep2Dto fileStep2Dto = new ReqESignUploadFileStep2Dto();
        fileStep2Dto.setContentMd5(fileContentMD5);
        fileStep2Dto.setFileUploadUrl(uploadUrl.getData().getFileUploadUrl());
        fileStep2Dto.setStream(SignatureUtils.getBytes(file));
        ResESignUploadFileStep2Dto uploadFile = SignatureUtils.uploadStream(fileStep2Dto);
        log.info("上传文件返回结果:{}", uploadFile);
        if (uploadFile == null) {
            this.removeById(req.getOrderId());
            throw new ServiceException("上传文件流失败");
        }
        if (0 != uploadFile.getErrCode()) {
            this.removeById(req.getOrderId());
            throw new ServiceException("上传文件流失败，错误为：" + uploadFile.getMsg());
        }
        //file.delete();
        //3.通过文件id，发起流程
        //3.1先根据文件id+关键字获取签章位置（发起流程时必须要在签署区信息写入签章坐标）
        ReqGetPositionsDto reqGetPositionsDto = new ReqGetPositionsDto();
        List<String> key = new ArrayList<>();
        key.add("甲方签名");
        key.add("乙方签名");
        reqGetPositionsDto.setKeywords(key);
        reqGetPositionsDto.setFileId(fileId);
        ResGetPositionsDto positions = SignatureUtils.getPositions(reqGetPositionsDto, seal);
        if (0 != positions.getCode()) {
            this.removeById(req.getOrderId());
            throw new ServiceException("获取签章坐标失败");
        }
        if (positions.getData().getKeywordPositions() == null) {
            this.removeById(req.getOrderId());
            throw new ServiceException("获取签章坐标失败");
        }
        float positionOrgX;
        float positionOrgY;
        float positionPersonX;
        float positionPersonY;
        try {
             positionOrgX = positions.getData().getKeywordPositions().get(0).getPositions().get(0).getCoordinates().get(0).getPositionX();
             positionOrgY = positions.getData().getKeywordPositions().get(0).getPositions().get(0).getCoordinates().get(0).getPositionY();
             positionPersonX = positions.getData().getKeywordPositions().get(1).getPositions().get(0).getCoordinates().get(0).getPositionX();
             positionPersonY = positions.getData().getKeywordPositions().get(1).getPositions().get(0).getCoordinates().get(0).getPositionY();
        }catch (Exception e){
            throw new ServiceException("获取签章坐标失败");
        }

        //组装参数ing
        ReqESignStartSignDto startSign = new ReqESignStartSignDto();
        //文件id
        List<ReqESignStartSignDto.DocsDto> list = new ArrayList<>();
        ReqESignStartSignDto.DocsDto docsDto = new ReqESignStartSignDto.DocsDto();
        docsDto.setFileId(fileId);
        list.add(docsDto);
        startSign.setDocs(list);
        //签署流程配置项
        ReqESignStartSignDto.SignFlow signFlow = new ReqESignStartSignDto.SignFlow();
        signFlow.setSignFlowTitle(getFileName(order));
        startSign.setSignFlowConfig(signFlow);

        //签署发起方：23.12.11：应客户需求，写死
        SignFlowInitiator signFlowInitiator = new SignFlowInitiator();
        SignFlowInitiator.OrgInitiator orgInitiator = new SignFlowInitiator.OrgInitiator();
        orgInitiator.setOrgId(seal.getOrgId());
        Transactor transactor = new Transactor();
        transactor.setPsnId(seal.getPsnId());
        orgInitiator.setTransactor(transactor);
        signFlowInitiator.setOrgInitiator(orgInitiator);
        startSign.setSignFlowInitiator(signFlowInitiator);

        //签署方信息(机构方+个人方)
        List<ReqESignStartSignDto.Signers> signersList = new ArrayList<>();
        //==========机构方========//
        ReqESignStartSignDto.Signers signers = new ReqESignStartSignDto.Signers();
        signers.setSignerType(1);
        //机构方配置信息
        SignConfig signConfig = new SignConfig();
        signConfig.setSignOrder(1);
        signers.setSignConfig(signConfig);
        //机构方签署区信息
        List<SignFields> SignFieldsList = new ArrayList<>();
        SignFields signFields = new SignFields();
        signFields.setCustomBizNum("001");
        signFields.setFileId(fileId);
        //机构方签章区配置项
        NormalSignFieldConfig normalSignFieldConfig = new NormalSignFieldConfig();
        SignFieldPosition signFieldPosition = new SignFieldPosition();
        signFieldPosition.setPositionPage(Integer.toString(pdfPage));
        signFieldPosition.setPositionX(positionOrgX);
        signFieldPosition.setPositionY(positionOrgY);
        normalSignFieldConfig.setSignFieldPosition(signFieldPosition);
        normalSignFieldConfig.setAutoSign(true);
        //印章id：23.12.11：应客户需求，写死
        //24.2.19更换一次
        normalSignFieldConfig.setAssignedSealId(seal.getEsignSealId());

        signFields.setNormalSignFieldConfig(normalSignFieldConfig);
        SignFieldsList.add(signFields);
        signers.setSignFields(SignFieldsList);
        signersList.add(signers);
        //==========机构方========//

        //==========个人方========//
        ReqESignStartSignDto.Signers person = new ReqESignStartSignDto.Signers();
        person.setSignerType(0);
        //个人签署方信息
        PsnSignerInfo psnSignerInfo = new PsnSignerInfo();
        psnSignerInfo.setPsnAccount(order.getCustomPhone());
        PsnInfo psnInfo = new PsnInfo();
        psnInfo.setPsnName(order.getCustomName());
        psnSignerInfo.setPsnInfo(psnInfo);
        person.setPsnSignerInfo(psnSignerInfo);
        //配置信息
        SignConfig personConfig = new SignConfig();
        personConfig.setSignOrder(2);
        personConfig.setForcedReadingTime(10);
        person.setSignConfig(personConfig);
        //个人方签署区信息
        List<SignFields> personFieldsList = new ArrayList<>();
        SignFields personFields = new SignFields();
        personFields.setCustomBizNum("002");
        personFields.setFileId(fileId);
        //个人方签章区配置项
        NormalSignFieldConfig personSignFieldConfig = new NormalSignFieldConfig();
        SignFieldPosition personFieldPosition = new SignFieldPosition();
        personFieldPosition.setPositionPage(Integer.toString(pdfPage));
        personFieldPosition.setPositionX(positionPersonX);
        personFieldPosition.setPositionY(positionPersonY);
        personSignFieldConfig.setSignFieldPosition(personFieldPosition);
        personFields.setNormalSignFieldConfig(personSignFieldConfig);
        personFieldsList.add(personFields);
        person.setSignFields(personFieldsList);
        signersList.add(person);

        startSign.setSigners(signersList);
        ResESignStartSignDto signDto = SignatureUtils.startSign(startSign, seal);
        if (signDto != null && signDto.getCode() != null && 0 != signDto.getCode()) {
            this.removeById(req.getOrderId());
            throw new ServiceException(signDto.getMessage());
        }
        String signFlowId = signDto.getData().getSignFlowId();
        //添加签署流程id到订单
        update(Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderId,req.getOrderId()).set(Order::getSignFlowId,signFlowId));
        //4.根据签署流程id，获取签署页面链接
        ReqESignShowSignFlowUrlDto showSignFlow = new ReqESignShowSignFlowUrlDto();
        showSignFlow.setSignFlowId(signFlowId);
        SignatureUtils.startSignFlow(showSignFlow, seal);
        ResESignShowSignFlowUrlDto showSignFlowUrlDto = SignatureUtils.showSignFlowUrl(showSignFlow, seal);
        if (0 != showSignFlowUrlDto.getCode()) {
            this.removeById(req.getOrderId());
            throw new ServiceException(showSignFlowUrlDto.getMessage());
        }

        res.setShortUrl(showSignFlowUrlDto.getData().getShortUrl());
        res.setUrl(showSignFlowUrlDto.getData().getUrl());
        return res;
    }

    @Override
    public ResESignGetSignFlowDetailDto getSignDetail(ReqESignGetSignFlowDetailDto req) {
        Order order = getSimpleOrder(req.getOrderId());
        if (order == null) {
            throw new ServiceException("未查询到订单详情");
        }
        //如果不是E签宝合同，那么直接返回成功
        if(order.getEsignContract().equals("N")){
            return ResESignGetSignFlowDetailDto.getSignFlowDetail(2);
        }
        Seal seal = sealService.getById(order.getSealId());
        if (seal == null) {
            throw new ServiceException("未查询到印章");
        }
        return SignatureUtils.getSignFlowDetail(order.getSignFlowId(), seal);
    }

    @Override
    public ResESignDownloadDto download(ReqESignDownloadDto req) {
        Order order = getSimpleOrder(req.getOrderId());
        if (order == null) {
            throw new ServiceException("未查询到订单详情");
        }
        if(order.getEsignContract().equals("N")){
            return ResESignDownloadDto.getSimpleDownload(configUtil.getUrl() + order.getFilePath());
        }
        Seal seal = sealService.getById(order.getSealId());
        if (seal == null) {
            throw new ServiceException("未查询到印章");
        }
        return SignatureUtils.getSignDownload(order.getSignFlowId(), seal);
    }

    @Override
    public boolean orderUpdate(ReqOrderUpdateDto req) {
        //删除
        fileService.removeFile(req.getOrderId());
        fileService.saveFileList(req.getOrderId(),req.getFileList());
        return true;
    }

    @Override
    public boolean updateOrder(ReqOrderUpdateAdminDto req) {
        Order order = getSimpleOrder(req.getOrderId());
        Assert.notNull(order,"未查询到订单详情");
        update(Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderId,req.getOrderId())
                .set(Order::getType,req.getType())
                .set(Order::getPayType,req.getPayType()));
        return true;
    }


    @Override
    public Map<String, Map<String, Object>> setPicMap(ReqOrderExportIdDto req) {
        Map<String, Map<String, Object>> imgsDataMap = new HashMap<>();
        List<Order> orderList = list(new LambdaQueryWrapper<Order>()
                        .select(Order::getOrderId,Order::getDeptId,Order::getSelfField,Order::getCustomName)
                        .in(Order::getOrderId,req.getOrderIds()));
        //获取图片
        List<String> orderIdList = orderList.stream().map(Order::getOrderId).collect(Collectors.toList());
        List<Long> deptIdList = orderList.stream().map(Order::getDeptId).collect(Collectors.toList());
        Map<Long,String> deptMap = deptService.selectDeptByIds(deptIdList).stream().collect(Collectors.toMap(SysDept::getDeptId,SysDept::getDeptName));
        Map<String,List<File>> fileMap = fileService.list(new LambdaQueryWrapper<File>().in(File::getSourceId,orderIdList)).stream().collect(Collectors.groupingBy(File::getSourceId));
        orderList.forEach(m->{
            Map<String, Object> imgsMap = new HashMap<>();
            //获取图片
            fileMap.getOrDefault(m.getOrderId(),new ArrayList<>()).forEach(n->{
                if(n.getFileName()!=null){
                    String fileName = n.getFileName().replaceAll("/","");
                    imgsMap.put(fileName,configUtil.getUrl()+n.getUri());
                }
            });
            //文件夹命名为：经销商名称+客户名字+车型+排量
            String deptName = deptMap.getOrDefault(m.getDeptId(),"");
            String customName  = m.getCustomName();
            String brandName;
            String pl;
            StringBuilder name = new StringBuilder(deptName + "-" + customName);
            if(m.getSelfField()!=null){
                JSONArray jsons = JSONArray.parseArray(m.getSelfField());
                List<ResSycDto> resSycDtos = jsons.toJavaList(ResSycDto.class);
                for (ResSycDto resSycDto : resSycDtos) {
                    if(resSycDto.getInsertData().equals("车型")){
                        brandName = resSycDto.getValue();
                        name.append("-").append(brandName);
                    }else if(resSycDto.getInsertData().equals("排量")){
                        pl = resSycDto.getValue();
                        name.append("-").append(pl);
                    }
                }
            }
            imgsDataMap.put(name.toString(),imgsMap);
        });
        return imgsDataMap;
    }

    @Override
    public ResPlaceAnOrderDto placeAnOrder(ReqPlaceAnOrderDto req) {
        Seal seal = sealService.getById(req.getSealId());
        Assert.notNull(seal, "未找到印章");
        Product product = productService.getById(req.getProductId());
        Assert.notNull(product, "未找到产品");
        if(product.getEsignContract().equals("Y")){
            if(StrUtil.isBlank(seal.getAppId()) ||
                    StrUtil.isBlank(seal.getAppSecret()) ||
                    StrUtil.isBlank(seal.getOrgId()) ||
                    StrUtil.isBlank(seal.getPsnId()) ||
                    StrUtil.isBlank(seal.getEsignSealId()) ){
                throw new ServiceException("印章:"+seal.getSealName()+"没有配置完整的E签宝属性，请联系系统管理员配置");
            }
        }
        //判断对接E签宝的问题
        //校验是否开启支付
        if (req.getOrderType() == 1) {
            if (seal.getOnlineStatus().equals("N")) {
                throw new ServiceException("线上支付功能未开启");
            }
            Config config = PayUtil.CONFIG_MAP.get(seal.getSealId());
            Assert.notNull(config,seal.getSealName()+"未找到线上支付配置");
        }
        if (req.getOrderType() == 2) {
            if (seal.getOfflineStatus().equals("N")) {
                throw new ServiceException("线下支付功能未开启");
            }
        }
        //线上支付
        if (req.getOrderType() == 1 && StrUtil.isBlank(req.getOpenId())) {
            throw new ServiceException("没有openId不能发起支付");
        }
        //线下，返回支付图片
        if (req.getOrderType() == 2 && StrUtil.isBlank(seal.getOfflinePayPic())) {
            throw new ServiceException("该印章未设置线下支付二维码，请联系管理员");
        }
        //去生成支付订单
        PayOrder payOrder = payOrderService.generatePayOrder(req.getOrderType(), req.getSealId(), req.getProductId(),req.getMoney(),req.getOpenId());
        //线上支付
        if (req.getOrderType() == 1) {
            //返回支付订单id
            return new ResPlaceAnOrderDto(payOrder.getPayOrderId());
        }
        //线下支付
        if (req.getOrderType() == 2) {
            //返回支付图片
            return new ResPlaceAnOrderDto(payOrder.getPayOrderId(), seal.getOfflinePayPic());
        }
        throw new ServiceException("支付方式错误");
    }

    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<ResFinanceOrderPageDto> financePageQuery(ReqFinanceOrderPageDto req) {
        return baseMapper.financePageQuery(req);
    }


    @Override
    public void financeExport(ReqFinanceOrderPageDto req, HttpServletResponse response) {
        List<ResFinanceOrderPageDto> data = financePageQuery(req);
        ExcelUtil.export(data, ResFinanceOrderPageDto.class, "财务记录" + LocalDate.now(), response);
    }

    @Override
    public void financeImport(MultipartFile file) {
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new ServiceException("导入失败");
        }
        UploadDataListener<FinanceOrderImportDto> listener = new UploadDataListener<>();
        EasyExcel.read(inputStream, FinanceOrderImportDto.class, listener).sheet().doRead();
        List<FinanceOrderImportDto> list = listener.getData();
        if (list == null || list.isEmpty()) {
            throw new ServiceException("请填写数据");
        }
        List<String> orderIdList = list.stream().map(FinanceOrderImportDto::getOrderId).distinct().collect(Collectors.toList());
        org.springframework.util.Assert.isTrue(list.size() == orderIdList.size(), "订单id不能重复");
        for (FinanceOrderImportDto importDto : list) {
            org.springframework.util.Assert.isTrue(StrUtil.isNotBlank(importDto.getOrderId().trim()), "订单id不能为空");
            org.springframework.util.Assert.isTrue(StrUtil.isNotBlank(importDto.getIssueInvoice().trim()), "是否开发票不能为空");
            if (!(importDto.getIssueInvoice().trim().equals("是") || importDto.getIssueInvoice().trim().equals("否"))) {
                throw new ServiceException("是否开发票错误:" + importDto.getIssueInvoice());
            }
            try {
                LocalDateTimeUtils.formatLocalDate(importDto.getInvoiceDate());
            } catch (Exception e) {
                throw new ServiceException("开票时间错误:" + importDto.getInvoiceDate() + "正确格式：2025-01-15");
            }
        }
        List<Order> orderList = new ArrayList<>();
        for (FinanceOrderImportDto importDto : list) {
            Order order = new Order();
            order.setOrderId(importDto.getOrderId().trim());
            //order.setIssueInvoice(importDto.getIssueInvoice().trim().equals("是") ? 1 : 2);
            order.setInvoiceMoney(importDto.getInvoiceMoney());
            if (StrUtil.isNotBlank(importDto.getInvoiceDate())) {
                order.setInvoiceDate(LocalDateTimeUtils.formatLocalDate(importDto.getInvoiceDate().trim()));
            }
            orderList.add(order);
        }
        if (!orderList.isEmpty()) {
            updateBatchById(orderList);
        }
    }

    @Override
    public void delOrder(String orderId) {
        update(Wrappers.lambdaUpdate(Order.class).set(Order::getDelFlag,1).eq(Order::getOrderId,orderId));
    }

    @Override
    public boolean uploadInvoice(ReqOrderUploadInvoiceDto req) {
        int count = count(Wrappers.lambdaQuery(Order.class).eq(Order::getOrderId,req.getOrderId()));
        if(count == 0){
            throw new ServiceException("未找到订单");
        }
        String invoiceUris = "";
        if(req.getInvoiceUris() != null || (!req.getInvoiceUris().isEmpty())){
            invoiceUris = String.join(",", req.getInvoiceUris());
        }
        update(Wrappers.lambdaUpdate(Order.class)
                .eq(Order::getOrderId,req.getOrderId())
                .set(Order::getInvoiceStatus,3)
                .set(Order::getInvoiceUris,invoiceUris)
                .set(Order::getInvoiceDate,LocalDate.now())
                .set(Order::getUpdateTime,LocalDateTime.now()));
        return true;
    }


    /**
     * 获取合同名称
     * @param order
     * @return
     */
    private String getFileName(Order order){
        return order.getCustomName()+order.getCustomPhone()+".pdf";
    }





}








































